package com.um.springboot.starter.interceptors;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.um.springboot.starter.annotation.LoginRequired;
import com.um.springboot.starter.code.CommonCode;
import com.um.springboot.starter.helper.SessionHelper;
import com.um.springboot.starter.orm.entity.Response;
import com.um.springboot.starter.properties.HshProperties;
import com.um.springboot.starter.service.CommonService;
import com.um.springboot.starter.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;

/**
 * API 参数验证拦截器
 * @author 邓南辉
 * @date 2019/12/13
 * @copyright 广州优匠科技有限公司
 */
@Slf4j
@Aspect     //@Aspect注解就是告诉spring 这是一个aop类,AOP切面
@Component   //可理解为用spring的时候xml里面的<beans>标签,类中 @Bean可以理解为用Spring的时候xml里面的<bean>标签
@Order(value = AspectOrders.LOGIN_ORDER)
public class LoginRequiredInterceptor {

    @Resource
    private HttpServletRequest request;

    @Autowired
    SessionHelper sessionHelper;

    @Autowired
    private HshProperties hshProperties;

    @Autowired
    private CommonService commonService;


    //@Around注解 环绕执行，就是在调用之前和调用之后，都会执行一定的逻辑
    //@Around("@annotation(com.um.springboot.starter.annotation.LoginRequired)")
    @Around("execution(* com.um..controller.*.*(..)) || execution(* com.hsh..controller.*.*(..))")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {

        MethodSignature signature = (MethodSignature) pjp.getSignature();
        LoginRequired loginRequired = signature.getMethod().getAnnotation(LoginRequired.class);

        //如果从方法拿不到，则从当前类中拿是否有注解
        if(loginRequired == null)
            loginRequired = pjp.getTarget().getClass().getAnnotation(LoginRequired.class);

        //有注解的才需要验证用户是否登录
        if(loginRequired != null && loginRequired.required()) {

            if("session".equals(hshProperties.getConfig().getSessionType())) {
                Map sessionUser = sessionHelper.getSessionUser();
                if (sessionUser == null) {
                    return Response.failed(CommonCode.LoginExpired);
                }
            } else if ("sa-token".equals(hshProperties.getConfig().getSessionType())) {
                StpUtil.checkLogin();
            }else {
                String tokenStr = StringUtil.getTrim(request.getHeader(hshProperties.getToken().getKey()));
                Map tokenMap = commonService.queryEntity(hshProperties.getToken().getTableName(), hshProperties.getToken().getKey(), tokenStr);
                if (null == tokenMap) {
                    return Response.failed(CommonCode.LoginExpired);
                }

                Long expire = hshProperties.getToken().getExpire();
                if (expire > 0) {
                    long createDateTime = 0;
                    if(tokenMap.get("create_time") instanceof Date){
                        createDateTime = ((Date) tokenMap.get("create_time")).getTime();
                    }else if(tokenMap.get("create_time") instanceof LocalDateTime){
                        createDateTime = java.sql.Timestamp.valueOf(((LocalDateTime) tokenMap.get("create_time"))).getTime();
                    }

                    long between = DateUtil.between(new Date(), new Date(createDateTime), DateUnit.MINUTE);
                    if (between > expire) {
                        return Response.failed(CommonCode.LoginExpired);
                    }
                }
            }
        }

        //result的值就是被拦截方法的返回值
        return pjp.proceed();
    }

}
